// PerformanceTestingDlg.cpp : implementation file
//

#include "stdafx.h"
#include "PerformanceTesting.h"
#include "PerformanceTestingDlg.h"
#include "Marco.h"
#include "AboutDlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

static const WCHAR DEFAULT_INIPATH[] =	L".\\config.ini";

// CPerformanceTestingDlg dialog
CPerformanceTestingDlg::CPerformanceTestingDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CPerformanceTestingDlg::IDD, pParent),
	  m_perfCtrl(NULL),
	  m_delayStartTime(0),
	  m_isAutoStart(FALSE),
	  m_isAutoReboot(FALSE),
	  m_outputFilePrefix(L""),
	  m_outputFile(NULL),
	  m_executeCount(0)
{
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CPerformanceTestingDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CPerformanceTestingDlg, CDialog)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_WM_CLOSE()
	ON_WM_TIMER()
	//}}AFX_MSG_MAP
	ON_BN_CLICKED(ID_START, &CPerformanceTestingDlg::OnBnClickedStart)
	ON_BN_CLICKED(ID_STOP, &CPerformanceTestingDlg::OnBnClickedStop)
	ON_BN_CLICKED(IDC_CLEAREDIT, &CPerformanceTestingDlg::OnBnClickedClearedit)
END_MESSAGE_MAP()


// CPerformanceTestingDlg message handlers

BOOL CPerformanceTestingDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	// Add "About..." menu item to system menu.

	// IDM_ABOUTBOX must be in the system command range.
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL)
	{
		CString strAboutMenu;
		strAboutMenu.LoadString(IDS_ABOUTBOX);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// Set the icon for this dialog.  The framework does this automatically
	//  when the application's main window is not a dialog
	SetIcon(m_hIcon, TRUE);			// Set big icon
	SetIcon(m_hIcon, FALSE);		// Set small icon

	// TODO: Add extra initialization here

	DoCommand();

	return TRUE;  // return TRUE  unless you set the focus to a control
}

void CPerformanceTestingDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialog::OnSysCommand(nID, lParam);
	}
}

// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.

void CPerformanceTestingDlg::OnPaint()
{
	if (IsIconic())
	{
		CPaintDC dc(this); // device context for painting

		SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

		// Center icon in client rectangle
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// Draw the icon
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialog::OnPaint();
	}
}

void CPerformanceTestingDlg::OnClose()
{
	SAFE_DELETE( m_perfCtrl );
	if( m_outputFile ){
		fclose(m_outputFile);
		m_outputFile = NULL;
	}
	CDialog::OnClose();
}

void CPerformanceTestingDlg::_OnMessageCallback(LPCSTR msg)
{
	((CPerformanceTestingDlg*)(AfxGetApp()->m_pMainWnd))->PushMessage(msg);
}

void CPerformanceTestingDlg::PushMessage(LPCSTR msg)
{
	if(m_outputFile)
	{
		fwrite(msg, 1, strlen(msg), m_outputFile );
	}
	else
	{
		m_msg += msg;
		HWND hwnd = GetDlgItem(IDC_EDIT)->m_hWnd;

		::SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)m_msg.c_str());
	}
}

// The system calls this function to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CPerformanceTestingDlg::OnQueryDragIcon()
{
	return static_cast<HCURSOR>(m_hIcon);
}


void CPerformanceTestingDlg::OnBnClickedStart()
{
	if( !m_perfCtrl )
	{
		WCHAR curDir[MAX_PATH] = {0};
		WCHAR iniPath[MAX_PATH] = {0};

		GetModuleFileName(NULL, curDir, _MAX_PATH);
		PathRemoveFileSpec(curDir);
		PathAppend(iniPath, curDir);
		PathAppend(iniPath, DEFAULT_INIPATH);

		m_perfCtrl = new CPerformanceControl();
		m_perfCtrl->SetMessageCallback(this->_OnMessageCallback);
		m_perfCtrl->SetIniPath(iniPath);
		m_perfCtrl->Init();
	}
}

void CPerformanceTestingDlg::OnBnClickedStop()
{
	SAFE_DELETE( m_perfCtrl );
}


void CPerformanceTestingDlg::OnBnClickedClearedit()
{
	HWND hwnd = GetDlgItem(IDC_EDIT)->m_hWnd;
	::SendMessage(hwnd, WM_SETTEXT, 0, (LPARAM)L"");
	m_msg = "";
}

void CPerformanceTestingDlg::SetCommandLine(LPWSTR cmdline)
{
	LPWSTR* argv = NULL;
	int argc;
	argv = CommandLineToArgvW(cmdline, &argc);

	enum _flg{
		CMD_FLG_NONE = 0,
		CMD_FLG_AUTOREBOOT,
		CMD_FLG_AUTOSTART,
		CMD_FLG_OUTPUT_LOCAL_PREFIX,
		CMD_FLG_EXECUTE_COUNT,
	};
	_flg cur_flg = CMD_FLG_NONE;
	for (int i = 0; i < argc; ++i)
	{
		std::wstring cmd = argv[i];
		if (_wcsnicmp(argv[i], L"/", 1) == 0)
		{
			if(cmd == L"/autoreboot")
				cur_flg = CMD_FLG_AUTOREBOOT;
			else if(cmd == L"/autostart")
				cur_flg = CMD_FLG_AUTOSTART;
			else if(cmd == L"/outputlocalprefix")
				cur_flg = CMD_FLG_OUTPUT_LOCAL_PREFIX;
			else if(cmd == L"/executecount")
				cur_flg = CMD_FLG_EXECUTE_COUNT;
		}
		else
		{
			if(cur_flg == CMD_FLG_AUTOSTART)
			{
				m_isAutoStart = TRUE;
				m_delayStartTime = _wtoi(cmd.c_str()) * 1000;
			}
			else if(cur_flg == CMD_FLG_AUTOREBOOT)
			{
				m_isAutoReboot = TRUE;
				m_delayRebootTime = _wtoi(cmd.c_str()) * 1000;
			}
			else if(cur_flg == CMD_FLG_OUTPUT_LOCAL_PREFIX)
			{
				m_outputFilePrefix = cmd;
			}
			else if(cur_flg == CMD_FLG_EXECUTE_COUNT)
			{
				m_executeCount = _wtoi(cmd.c_str());
			}
		}
	}
}


void CPerformanceTestingDlg::DoCommand()
{
	if(m_isAutoStart)
	{
		m_timerDelayStart = SetTimer(TIMER_EVT_DELAYSTART, m_delayStartTime, 0);
	}
	if(m_isAutoReboot)
	{
		m_timerDelayReboot = SetTimer(TIMER_EVT_AUTOREBOOT, m_delayRebootTime, 0);
	}

	if(m_outputFilePrefix != L"")
	{
		WIN32_FIND_DATA findData;
		HANDLE hFind;

		std::wstring prefix = m_outputFilePrefix + L"*";
		std::wstring filename = L"";
		int idx = 1;
		hFind = FindFirstFileW(prefix.c_str(), &findData);
		if(hFind != INVALID_HANDLE_VALUE) 
		{
			do{
				filename = findData.cFileName;
			}while (FindNextFile(hFind, &findData));
		}
		FindClose(hFind);

		if( filename != L"" )
		{
			int len = filename.size();
			const wchar_t* c_filename = filename.c_str();
			if( len>=4 && wcscmp(&c_filename[len-4], L".log")==0 )
			{
				WCHAR strInt[16] = {0};
				int prefixSize = m_outputFilePrefix.size();
				wcsncpy( strInt, &c_filename[prefixSize+1/*include "_"*/], len-4-(prefixSize+1) );
				idx = _wtoi( strInt );
				idx += 1;
			}
		}

		if( m_executeCount>0 && idx<=m_executeCount )
		{
			WCHAR outputFileName[_MAX_PATH];
			wsprintf(outputFileName, L"%s_%d.log", m_outputFilePrefix.c_str(), idx);
			m_outputFile = _wfopen(outputFileName, L"w");
		}
	}
}

void CPerformanceTestingDlg::Reboot()
{
	if( !m_isAutoReboot )
		return;
	system("shutdown /r");
	OnClose();
}

void CPerformanceTestingDlg::OnTimer(UINT nIDEvent) 
{
	// Call base class handler.
	switch(nIDEvent)
	{
	case TIMER_EVT_DELAYSTART:
		KillTimer(m_timerDelayStart);
		OnBnClickedStart();
		break;
	case TIMER_EVT_AUTOREBOOT:
		KillTimer(m_timerDelayReboot);
		Reboot();
		break;
	default:
		break;
	}

	CDialog::OnTimer(nIDEvent);
}